const express = require('express');
const cors = require('cors');
const helmet = require('helmet');
const compression = require('compression');
const morgan = require('morgan');
const cookieParser = require('cookie-parser');
const session = require('express-session');
const RedisStore = require('connect-redis').default;
const rateLimit = require('express-rate-limit');
const mongoSanitize = require('express-mongo-sanitize');
const xss = require('xss');
const hpp = require('hpp');
const swaggerUi = require('swagger-ui-express');
const swaggerJsdoc = require('swagger-jsdoc');
const { createServer } = require('http');
const { Server } = require('socket.io');
require('express-async-errors');

// 导入配置
const config = require('./config/config');
const logger = require('./config/logger');
const database = require('./config/database');
const redis = require('./config/redis');

// 导入中间件
const { errorHandler } = require('./middleware/errorHandler');
const notFound = require('./middleware/notFound');
const auth = require('./middleware/auth');
const requestLogger = require('./middleware/requestLogger');
const responseTime = require('./middleware/responseTime');

// 导入路由
const authRoutes = require('./routes/auth');
const userRoutes = require('./routes/users');
const courseRoutes = require('./routes/courses');
const examRoutes = require('./routes/exams');

// 导入Socket.IO处理器
const socketHandler = require('./socket/socketHandler');

// 创建Express应用
const app = express();
const server = createServer(app);
const io = new Server(server, {
  cors: {
    origin: config.cors.origin,
    methods: ['GET', 'POST'],
    credentials: true
  }
});

// 设置Socket.IO
socketHandler(io);

// 信任代理
app.set('trust proxy', 1);

// 基础中间件
app.use(helmet({
  contentSecurityPolicy: {
    directives: {
      defaultSrc: ["'self'"],
      styleSrc: ["'self'", "'unsafe-inline'", 'https:'],
      scriptSrc: ["'self'", 'https:'],
      imgSrc: ["'self'", 'data:', 'https:'],
      connectSrc: ["'self'", 'https:', 'wss:'],
      fontSrc: ["'self'", 'https:'],
      objectSrc: ["'none'"],
      mediaSrc: ["'self'", 'https:'],
      frameSrc: ["'none'"]
    }
  },
  crossOriginEmbedderPolicy: false
}));

app.use(compression());
app.use(cors({
  origin: config.cors.origin,
  credentials: true,
  methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],
  allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With']
}));

// 请求日志
if (config.env === 'development') {
  app.use(morgan('dev'));
} else {
  app.use(morgan('combined', {
    stream: {
      write: (message) => logger.info(message.trim())
    }
  }));
}

// 解析中间件
app.use(express.json({ limit: '50mb' }));
app.use(express.urlencoded({ extended: true, limit: '50mb' }));
app.use(cookieParser());

// 安全中间件
app.use(mongoSanitize());
app.use((req, res, next) => {
  // XSS防护
  if (req.body) {
    Object.keys(req.body).forEach(key => {
      if (typeof req.body[key] === 'string') {
        req.body[key] = xss(req.body[key]);
      }
    });
  }
  next();
});
app.use(hpp());

// 会话配置
app.use(session({
  store: new RedisStore({ client: redis }),
  secret: config.session.secret,
  resave: false,
  saveUninitialized: false,
  cookie: {
    secure: config.env === 'production',
    httpOnly: true,
    maxAge: config.session.maxAge
  },
  name: 'sessionId'
}));

// 速率限制
const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15分钟
  max: config.rateLimit.max, // 限制每个IP的请求数
  message: {
    error: '请求过于频繁，请稍后再试',
    code: 'RATE_LIMIT_EXCEEDED'
  },
  standardHeaders: true,
  legacyHeaders: false,
  skip: (req) => {
    // 跳过健康检查和静态资源
    return req.path === '/health' || req.path.startsWith('/static/');
  }
});
app.use(limiter);

// 自定义中间件
app.use(requestLogger);
app.use(responseTime);

// 静态文件服务
app.use('/static', express.static('public', {
  maxAge: '1d',
  etag: true,
  lastModified: true
}));

// API文档配置
const swaggerOptions = {
  definition: {
    openapi: '3.0.0',
    info: {
      title: '在线学习平台 API',
      version: '1.0.0',
      description: '在线学习平台后端API文档',
      contact: {
        name: 'RX Team',
        email: 'support@rxbase.com'
      }
    },
    servers: [
      {
        url: config.app.baseUrl,
        description: '开发环境'
      }
    ],
    components: {
      securitySchemes: {
        bearerAuth: {
          type: 'http',
          scheme: 'bearer',
          bearerFormat: 'JWT'
        }
      }
    },
    security: [
      {
        bearerAuth: []
      }
    ]
  },
  apis: ['./src/routes/*.js', './src/models/*.js']
};

const swaggerSpec = swaggerJsdoc(swaggerOptions);

// API文档路由
if (config.env !== 'production') {
  app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec, {
    explorer: true,
    customCss: '.swagger-ui .topbar { display: none }',
    customSiteTitle: '在线学习平台 API 文档'
  }));
}

// 健康检查
app.get('/health', (req, res) => {
  res.status(200).json({
    status: 'OK',
    timestamp: new Date().toISOString(),
    uptime: process.uptime(),
    environment: config.env,
    version: process.env.npm_package_version || '1.0.0',
    memory: process.memoryUsage(),
    database: database.sequelize.authenticate() ? 'connected' : 'disconnected',
    redis: redis.status === 'ready' ? 'connected' : 'disconnected'
  });
});

// API路由
const apiRouter = express.Router();

// 公开路由（无需认证）
apiRouter.use('/auth', authRoutes);
apiRouter.use('/courses', courseRoutes); // 部分课程信息可公开访问

// 需要认证的路由
apiRouter.use('/users', auth.authenticate, userRoutes);
apiRouter.use('/exams', auth.authenticate, examRoutes);

// 挂载API路由
app.use('/api', apiRouter);

// 根路由
app.get('/', (req, res) => {
  res.json({
    message: '欢迎使用在线学习平台API',
    version: '1.0.0',
    documentation: config.env !== 'production' ? '/api-docs' : null,
    health: '/health',
    timestamp: new Date().toISOString()
  });
});

// 404处理
app.use(notFound);

// 错误处理
app.use(errorHandler);

// 优雅关闭处理
process.on('SIGTERM', gracefulShutdown);
process.on('SIGINT', gracefulShutdown);

function gracefulShutdown(signal) {
  logger.info(`收到 ${signal} 信号，开始优雅关闭...`);
  
  server.close(() => {
    logger.info('HTTP服务器已关闭');
    
    // 关闭数据库连接
    database.sequelize.close().then(() => {
      logger.info('数据库连接已关闭');
    }).catch(err => {
      logger.error('关闭数据库连接时出错:', err);
    });
    
    // 关闭Redis连接
    redis.disconnect();
    logger.info('Redis连接已关闭');
    
    // 关闭Socket.IO
    io.close(() => {
      logger.info('Socket.IO服务器已关闭');
    });
    
    process.exit(0);
  });
  
  // 强制关闭超时
  setTimeout(() => {
    logger.error('强制关闭应用');
    process.exit(1);
  }, 10000);
}

// 未捕获异常处理
process.on('uncaughtException', (err) => {
  logger.error('未捕获的异常:', err);
  process.exit(1);
});

process.on('unhandledRejection', (reason, promise) => {
  logger.error('未处理的Promise拒绝:', reason);
  logger.error('Promise:', promise);
  process.exit(1);
});

// 启动服务器
const PORT = config.app.port || 3000;
const HOST = config.app.host || '0.0.0.0';

server.listen(PORT, HOST, async () => {
  try {
    // 测试数据库连接
    await database.sequelize.authenticate();
    logger.info('数据库连接成功');
    
    // 同步数据库模型（仅在开发环境）
    if (config.env === 'development') {
      await database.sequelize.sync({ alter: true });
      logger.info('数据库模型同步完成');
    }
    
    logger.info(`服务器运行在 http://${HOST}:${PORT}`);
    logger.info(`环境: ${config.env}`);
    
    if (config.env !== 'production') {
      logger.info(`API文档: http://${HOST}:${PORT}/api-docs`);
    }
    
  } catch (error) {
    logger.error('启动服务器时出错:', error);
    process.exit(1);
  }
});

// 导出app和server供测试使用
module.exports = { app, server, io };